Bleutooth




■ Bluetooth BLEモード
   RN4020によるPC(VC#) - PIC32MZ間I/O、文字列送受信

         (PIC32MZ評価ボード サンプルソフト)

(サンプルプログラム(VC#プロジェクトファイル VC# 2017版) → ダウンロード
(サンプルプログラム(実行ファイル) → ダウンロード

                               ★PIC側プログラム → URL

<仕様>
・Bluetooth BLEモードによる PCとPIC32MZ間の送受信を行うこと。
・PC側 及びPIC側のBluetoothデバイスとして マイクロチップのRN4020を使用すること
 また、RN4020が実装された無線モジュールとして マイクロエレクトロニカ(株)のBLE2 Clickを使用のこと
・PC側がセントラル、PIC側がペリフェラルとする
・PICはPIC32MZ2048EFH100を使用のこと。
・PIC側のRN4020とPICとの送受信(UART)コマンドの内容を 別のUARTによりPCのTera Termでモニタできること
 また、キャラクタ液晶でも送受信コマンドをモニタできること。
・PC側のアプリケーションはVC#で作成のこと
・PC側のRN4020とPC間の送受信(UART)コマンドの内容を PCのアプリケーションの中でモニタできること。
・PCとPIC間のI/O制御、文字列送受信としては以下ができること。
  ➀ PC側アプリケーションのボタンのクリックで PIC側のLEDをON/OFFできること
  ➁ PIC側スイッチのON/OFFを PC側アプリケーションでモニタできること
  ③ PIC側の可変抵抗器の電圧値を PC側のテキストボックスで表示し、 
    また、プログレスバーでも値のイメージを表示すること
  ④ PIC側アプリケーションから 以下の文字列をPIC側に送信した場合以下の返信がされること
        送信文字列      返信文字列
     1. Japan       →   Tokyo
     2. America     →   Washinton
     3. U.K.        →   London
     4. France      →   Paris
     5. その他      →   Pardon ?

・その他のBLEデバイスとして、市販のBLE機器(オムロン 環境センサ 2JCIE-BL01など)なども検出して、接続ができること。
・PIC側では可変抵抗器の電圧が、I2C制御のキャラクタ液晶でモニタできること。


 (PC側アプリケーション例)


以下、プログラム抜粋

Form1.cs [デザイン]
Form1.cs

          

   

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; //追加 シリアルポートコンポーネント用 namespace _102_COM_test { public partial class Form1 : Form { int CommandNum,CommandNum2; int Flag_EchoOff; int LedMode = 0; string str2; string str3; string str4; string strMacAdrs; string strMacAdrsType; char AlternativeChar = '0'; //交互文字型フラグ Byte[] OUTBuffer = new byte[20]; //送信バッファー Byte[] INBuffer = new byte[20]; //受信バッファー //文字を変換するクラスを宣言 Encoding encSjis = Encoding.GetEncoding("shift-jis"); Encoding encUni = Encoding.GetEncoding("unicode"); delegate void ReceiveDelegate(string str);//デリゲート宣言 public Form1() { InitializeComponent(); SendDataBtn.Visible = false; ManuSendBtn.Visible = false; SendDataCBox.Visible = false; LedBtn.BackColor = Color.DarkGray;//ダークグレー色 pictureBox1.Visible = false; pictureBox2.Visible = true; OffSw_pictureBox.Visible = true; //SW オフ画像表示 OnSw_pictureBox.Visible = false; //SW オン画像表示 //接続状態表示ランプの表示 pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height);//Widthxhight: 75x75 //pictureBox1のイメージデータのオブジェクト生成 Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成 g.FillEllipse(Brushes.Gray, 0, 0, 50, 50);//灰色塗りつぶし 基点(0,0) 幅×高さ:50×50 VR_progressBar.Value = 0; SendDataCBox.Items.Clear(); SendDataCBox.Items.Add("+//Echo OnOff"); SendDataCBox.Items.Add("SF,1//Initialize RN4020"); SendDataCBox.Items.Add("SR,80000000//Set Central Mode"); SendDataCBox.Items.Add("R,1//Reboot"); SendDataCBox.Items.Add("D//Device Info"); SendDataCBox.Items.Add("F//Start Scan"); SendDataCBox.Items.Add("X//Stop Scan"); SendDataCBox.Items.Add("E//Establish Connection"); SendDataCBox.Items.Add("Z"); SendDataCBox.Items.Add("Z//Stop Connecting"); SendDataCBox.Items.Add("LS//List Server Services"); SendDataCBox.Items.Add("LC//List Client Services"); SendDataCBox.Items.Add("CHW,000B,4041424344454647484940414243444546474849//Write value of client handle"); SendDataCBox.Items.Add("CHW,000B,45464748//Write EFGH value of client handle"); SendDataCBox.Items.Add("CHW,000B,494A4B4C//Write IJKL value of client handle"); SendDataCBox.Items.Add("CHR,000B//Read value of client handle"); SendDataCBox2.Items.Clear(); SendDataCBox2.Items.Add("Japan"); SendDataCBox2.Items.Add("America"); SendDataCBox2.Items.Add("U.K."); SendDataCBox2.Items.Add("France"); SendDataCBox2.Items.Add("How are you ?"); SendDataCBox2.SelectedIndex = 0; string[] PortList = SerialPort.GetPortNames(); foreach (string PortName in PortList) { ComCBox.Items.Add(PortName); } if (ComCBox.Items.Count > 0) { ComCBox.SelectedIndex = 0; } } private void ConnectBtn_Click(object sender, EventArgs e) { if (serialPort1.IsOpen == true) // シリアルポートがオープンしている場合 { serialPort1.Close(); //COMポートを閉じる } try { serialPort1.PortName = ComCBox.SelectedItem.ToString(); //serialPort1.PortName = "COM3"; //COM1 ポート使用 //serialPort1.PortName = "COM5"; //COM1 ポート使用 //再設定:必須 serialPort1.BaudRate = 115200; //9600bps serialPort1.Parity = System.IO.Ports.Parity.None; //パリティなし serialPort1.DataBits = 8; //データ長 8ビット serialPort1.StopBits = System.IO.Ports.StopBits.One; //ストップビット 1 serialPort1.ReadTimeout = 500; //500mse 読み込みタイムアウト時間 serialPort1.WriteTimeout = 500; //500msec書き込みタイムアウト時間 serialPort1.Open();//シリアルポートオープン SendDataBtn.Visible = true; ManuSendBtn.Visible = true; SendDataCBox.Visible = true; } catch (Exception ex) { DialogResult result = MessageBox.Show (ex.Message + "\n" + "COMポートがひらけません。\n" + " <対応例>\n" + "  ・COMポート変更\n" + "  ・COMポートを接続してから本アプリケーションを再起動"); SendDataBtn.Visible = false; ManuSendBtn.Visible = false; SendDataCBox.Visible = false; } } private void SendData(string myString) { if (!myString.EndsWith("\r")) myString += "\r"; //改行が無かったら \rを追加する Byte[] byteArry = encSjis.GetBytes(myString); //'送信文字をShift-jisに変換してをByte配列に格納 serialPort1.Write(byteArry, 0, byteArry.Length); //送信 } private void SendDataBtn_Click(object sender, EventArgs e) //自動コマンド送信ボタン { serialPort1.DiscardInBuffer(); //受信バッファのデータクリア SendData("+//Echo OnOff"); timer1.Interval = 3000; timer1.Enabled = true; CommandNum = 1; } //削除条件を定義するデリゲート static bool strCheck(string str) //,,,,が4個以上のみ摘出 { bool judge; int startPosi = 0; int endPosi = 0; int Num = 0; do { endPosi = str.IndexOf(",", startPosi); //label3.Text = "指定文字列が ","x 4個以下の要素を削除の場合""; if (endPosi >= 0) { startPosi = endPosi + 1; Num++; //指定文字列の数をカウント } } while (endPosi >= 0); if (Num <= 3) { judge = true; // , が4個以下の要素を削除 //要素削除 } else { judge = false; //要素 非削除 } return judge; } private void SetText(string str) { richTextBox1.AppendText(str); //文字列追加 if ((CommandNum == 7) || (CommandNum2 == 2)) { str2 = str2 + str; } if (CommandNum == 8) { str3 = str; } if(CommandNum == 10) { str4 = str; try { if (str4.IndexOf("Notify,000E,11") >= 0) //Notify,000E,10./ Notify,000E,11.の場合 { if (str4[15] == '1') //SW1 : ONの場合 { OnSw_pictureBox.Visible = true; OffSw_pictureBox.Visible = false; pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height); //pictureBox1のイメージデータのオブジェクト生成 Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成 g.FillEllipse(Brushes.Orange, 0, 0, 50, 50);//橙色塗りつぶし 基点(10,0) 幅×高さ:50×50 } else //SW1:OFFの場合 { OnSw_pictureBox.Visible = false; OffSw_pictureBox.Visible = true; pictureBox5.Image = new Bitmap(pictureBox5.Width, pictureBox5.Height); //pictureBox1のイメージデータのオブジェクト生成 Graphics g = Graphics.FromImage(pictureBox5.Image); //イメージからグラフィックスを作成 g.FillEllipse(Brushes.Gray, 0, 0, 50, 50);//灰色塗りつぶし 基点(10,0) 幅×高さ:50×50 } } //可変抵抗器VRのAD変換値処理 if (str4.IndexOf("Notify,000E,12") >= 0) //Notify,000E,12XXXX の場合 { string strVR = str4[14].ToString() + str4[15].ToString() + str4[16].ToString() + str4[17].ToString(); int adcValue = Convert.ToInt32(strVR, 16);//16進数文字列を 10進数に変換 ADCMonitor((uint)adcValue); //プログレスバー表示、電圧値表示 } //文字列返信の場合 if (str4.IndexOf("Notify,000E,13") >= 0) //Notify,000E,13XXXX の場合 { string input = str4.Substring(str4.IndexOf("Notify,000E,13") + 14); input = input.Replace(".", ""); input = input.Replace(" ", ""); input = input.Replace("\r", ""); //必須 これがないと後の16進文字列→標準文字列変換がうまく動作しない input = input.Replace("\n", ""); //必須 これがないと後の16進文字列→標準文字列変換がうまく動作しない int Num = 0; int i; byte[] array2 = new byte[input.Length / 2]; //shift-JIS バイト配列 for (i = 0; i < input.Length; i = i + 2) { string strXX = input.Substring(i, 2); //先頭からi番目から 2個づつ文字列化 array2[Num] = Convert.ToByte(strXX, 16); // 16進数文字列x2個を 標準文字x1個に変換 Num++; } byte[] byteUni = Encoding.Convert(encSjis, encUni, array2); //shift-jis からunicodeの配列に変換する string strUni = encUni.GetString(byteUni); //配列を文字列に変換 richTextBox3.AppendText(strUni); //文字列追加 richTextBox3.AppendText("\n"); //改行 } } catch { } } //カレット位置を末尾に移動 richTextBox1.SelectionStart = richTextBox1.Text.Length; //テキストボックスにフォーカスを移動 richTextBox1.Focus(); //カレット位置までスクロール richTextBox1.ScrollToCaret(); if (str.IndexOf("Echo Off") != -1) Flag_EchoOff = 1; //"Echo Off"を含む文字列が返ってきたらFlag_EchoOff = 1; } private void ClearBtn_Click(object sender, EventArgs e) { richTextBox1.Clear(); } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] byteRead = new byte[serialPort1.BytesToRead]; //受信文字 serialPort1.Read(byteRead, 0, serialPort1.BytesToRead);//読み込み byte[] byteUni = Encoding.Convert(encSjis, encUni, byteRead); //shift-jis からunicodeに変換する string strUni = encUni.GetString(byteUni); //配列を文字列に変換 ReceiveDelegate receiveDelegate = new ReceiveDelegate(SetText); this.Invoke(receiveDelegate, strUni); } private void ComCBox_TextChanged(object sender, EventArgs e) { SendDataBtn.Visible = false; if (serialPort1.IsOpen == true) // シリアルポートがオープンしている場合 { serialPort1.Close(); //COMポートを閉じる } } private void timer1_Tick(object sender, EventArgs e) { switch (CommandNum) { case 1: if (Flag_EchoOff == 1) //"Echo Off"が戻ってきた場合 → Echo Onに変更 { Flag_EchoOff = 0; SendData("+//Echo OnOff"); CommandNum = 1; break; } SendData("SF,1//Initialize RN4020"); timer1.Interval = 2000; CommandNum++; break; case 2: SendData("SR,80000000//Set Features, Central Mode"); //セントラルモード CommandNum++; break; case 3: SendData("SN,central_ysPC"); //デバイス名称設定 CommandNum++; break; case 4: SendData("R,1//Reboot"); //RN4020 リブート CommandNum++; break; case 5: SendData("+//Echo OnOff"); //リブート後は Echo Offなので、Echo On に設定 CommandNum++; break; case 6: CommandNum++; SendData("F//Start Scan"); //スキャン開始 timer1.Interval = 4000; break; case 7: CommandNum++; timer1.Interval = 2000; string[] array1 = str2.Split('\n'); //\nで分割、\nは削除される List<string> list1 = new List<string>(array1); //リスト作成 list1.RemoveAll(strCheck); //条件にもとづくリスト作成 richTextBox2.AppendText(String.Join("\n", list1)); //リストを \n で結合し テキストボックスに表示); break; case 8: if (str3 == "Connected\r\n") //★Retには\r\nが含まれている //接続完了まで待つ { timer1.Interval = 2000;//"Connected\r\n" 検出1000msec後 SW ON/OFF指令送信 CommandNum++; SendData("LC//List Client Services"); } break; case 9: //SWの状態変化、及びVRの電圧変化 SendData("CHW,000F,0100//Set Notification"); //ペリフェラルのキャラクタリスティックに書き込みがあった場合、 //セントラルに告知する。 //返信用の首都名の変化(上書き書き込み) SendData("CHW,0015,0100//Set Notification"); //ペリフェラルのキャラクタリスティックに書き込みがあった場合、 //セントラルに告知する。 SendData("CHW,000B,10"); //LED3:OFF 初期値 初期LED3点灯対策 CommandNum++; break; case 10: //無限ループ break; default: break; } } private void ManuSendBtn_Click(object sender, EventArgs e) //手動コマンド送信ボタン { //serialPort1.DiscardInBuffer(); //受信バッファのデータクリア //string strSend = SendDataCBox.Text; //if (!strSend.EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する //Byte[] byteArry = encSjis.GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納 //serialPort1.Write(byteArry, 0, byteArry.Length); //送信 } private void richTextBox1_SelectionChanged(object sender, EventArgs e) { //文字列 string str = richTextBox1.Text; //カーソル位置を取得 int selectPos1 = richTextBox1.SelectionStart; int selectPos = richTextBox1.SelectionStart; //カーソルの位置までの行を数える int row = 1, startPos = 0; for (int endPos = 0; (endPos = str.IndexOf('\n', startPos)) < selectPos && endPos > -1; row++) { startPos = endPos + 1; } //列の計算 int col = selectPos - startPos + 1; } private void DeviceConnectBtn_Click(object sender, EventArgs e) { } private void Re_ScanBtn_Click(object sender, EventArgs e) { //richTextBox2.Clear(); //Bluetooth デバイス一覧ボックス クリア //str2 = ""; //serialPort1.DiscardInBuffer(); //受信バッファのデータクリア //SendData("X//Stop Scan"); //スキャン停止 //timer2.Interval = 100; //timer2.Enabled = true; //CommandNum2 = 1; } private void richTextBox2_SelectionChanged_1(object sender, EventArgs e) { int CurrentPosi; //全文字列に於ける、カーソルの現在位置 int row; //カーソルの行位置 int startPosi; //str.IndexOf(char*, startPosi) 検索を開始する列位置 int endPosi; int startPosi2 = 0; //str.IndexOf(char*, startPosi) 検索を開始する列位置 int endPosi2; int Num = 0; string DeviceName; //デバイス名 string str = richTextBox2.Text; //全文字列における、カーソルの現在位置を取得 CurrentPosi = richTextBox2.SelectionStart; //カーソルの前にある全文字数(含む\n)を取得できる // textBox1.Text = CurrentPosi.ToString(); //全文字列に於ける列の位置を表示 //カーソルの位置までの行を数える → 改行記号'\n'を数える row = 1; startPosi = 0; for (endPosi = 0; (endPosi = str.IndexOf('\n', startPosi)) < CurrentPosi && endPosi > -1; //str.IndexOf('\n', startPosi) →'\n'がある位置を返す row++) { startPosi = endPosi + 1; //'\n'があった位置+1 → 次の行の先頭の文字位置 } try { ////表示 string strLine = richTextBox2.Lines[row - 1];//選択文字列 //////カーソル行の文字列の選択 ////見つかった位置を選択開始の位置にする richTextBox2.SelectionStart = startPosi; ////探した文字列の長さを選択する文字列の長さにする richTextBox2.SelectionLength = strLine.Length; //アドレス取得 strMacAdrs = strLine.Substring(0, 12); textBox1.Text = strMacAdrs; //アドレスタイプ取得   //パブリックアドレス:0 ランダムアドレス:1 strMacAdrsType = strLine.Substring(13, 1); textBox4.Text = strMacAdrsType; //デバイス名取得 int NameLength = strLine.IndexOf(',', 15) - 15; //デバイス名の長さ if (NameLength == 0) DeviceName = "不明"; //長さ0の場合 else { DeviceName = strLine.Substring(15, NameLength); } textBox2.Text = DeviceName; //電波強度取得 do { endPosi2 = strLine.IndexOf(",", startPosi2); //label3.Text = "指定文字列が ","x 4個以下の要素を削除の場合""; if (endPosi2 >= 0) { startPosi2 = endPosi2 + 1; Num++; //指定文字列の数をカウント } } while (Num != 4); string dBmStr = strLine.Substring(endPosi2 + 1); int dBm; if (dBmStr[0] == '-') //負の場合 //1mW 以下の場合 { dBmStr = dBmStr.Substring(1); dBm = Convert.ToInt32(dBmStr, 16); //16進数文字列 → 10進整数 dBm = -dBm; } else dBm = Convert.ToInt32(dBmStr, 16); //正の場合 //1mW 以上の場合 textBox3.Text = dBm.ToString(); } catch { } } private void DeviceConnectBtn_Click_1(object sender, EventArgs e) { string strTemp = "E," + strMacAdrsType + "," + strMacAdrs + "//Connect"; SendData(strTemp); } private void Re_ScanBtn_Click_1(object sender, EventArgs e) { richTextBox2.Clear(); //Bluetooth デバイス一覧ボックス クリア str2 = ""; serialPort1.DiscardInBuffer(); //受信バッファのデータクリア SendData("X//Stop Scan"); //スキャン停止 timer2.Interval = 100; timer2.Enabled = true; CommandNum2 = 1; } private void ManuSendBtn_Click_1(object sender, EventArgs e) //手動コマンド送信ボタン { serialPort1.DiscardInBuffer(); //受信バッファのデータクリア string strSend = SendDataCBox.Text; if (!strSend.EndsWith("\r")) strSend += "\r"; //改行が無かったら \rを追加する Byte[] byteArry = encSjis.GetBytes(strSend); //'送信文字をShift-jisに変換してをByte配列に格納 serialPort1.Write(byteArry, 0, byteArry.Length); //送信 } private void LedBtn_Click(object sender, EventArgs e) { string sendStr; string LEDmode = "1"; if (AlternativeChar == '0') AlternativeChar = '1'; //呼ばれる毎に '0'/'1'を繰り返す else AlternativeChar = '0'; if (LedMode == 0) //LED ONの場合 { LedMode = 1; sendStr = "CHW,000B," + LEDmode + AlternativeChar; //LED ON SendData(sendStr); LedBtn.BackColor = Color.OrangeRed;//オレンジ色 pictureBox1.Visible = true; pictureBox2.Visible = false; } else { LedMode = 0; //LED OFFの場合 sendStr = "CHW,000B," + LEDmode + AlternativeChar; //LED OFF SendData(sendStr); LedBtn.BackColor = Color.DarkGray;//ダークグレー色 pictureBox1.Visible = false; pictureBox2.Visible = true; } } private void button1_Click(object sender, EventArgs e) { } private void timer3_Tick(object sender, EventArgs e) { string sendStr; if (AlternativeChar == '0') AlternativeChar = '1'; //呼ばれる毎に '0'/'1'を繰り返す else AlternativeChar = '0'; if (LedMode == 0) sendStr = "CHW,000B," + AlternativeChar + "0"; //LED OFFの場合 Data[8] = 1 else sendStr = "CHW,000B," + AlternativeChar + "1"; //LED ONの場合 Data[8] = 1 SendData(sendStr); } private void timer2_Tick(object sender, EventArgs e) { switch (CommandNum2) { case 1: SendData("F//Start Scan"); //スキャン開始 375 ms for scan interval, 250 ms for scan window CommandNum2++; timer2.Interval = 2000; break; case 2: string[] array1 = str2.Split('\n'); //\nで分割、\nは削除される List<string> list1 = new List<string>(array1); //リスト作成 list1.RemoveAll(strCheck); //条件にもとづくリスト作成 richTextBox2.AppendText(String.Join("\n", list1)); //リストを \n で結合し テキストボックスに表示); CommandNum2 = 0; timer2.Enabled = false; break; default: break; } } private string To_Hexadecimal(string input) //標準文字列 → 16進数表示文字列 変換関数 { int[] num = new int[input.Length]; //shift-JIS整数値 string[] HexaDecimal = new string[input.Length]; //変換後の16進数文字列 byte[] array1 = encSjis.GetBytes(input); //'送信文字をShift-jisに変換してをByte配列に格納 for (int i = 0; i < array1.Length; i++) { num[i] = array1[i]; //配列 HexaDecimal[i] = num[i].ToString("X"); //大文字文字で表示 } string ret = String.Join("", HexaDecimal); //区切り文字なしで文字列を結合 return ret; } private void SendDataBtn2_Click(object sender, EventArgs e) { try { serialPort1.DiscardInBuffer(); //受信バッファのデータクリア string strStdData = SendDataCBox2.Text; string strHexaData = To_Hexadecimal(strStdData); //標準文字列 → 16進数表示文字列 変換関数 string strTemp2 = "CHW,0011," + strHexaData; //0011:国名保存用 ペリフェラルキャラクタリスティックのハンドル SendData(strTemp2); //\rを追加して送信 } catch (Exception ex) { } } private void ClearReceiveStrBtn_Click(object sender, EventArgs e) //受信文字列表示リッチテキストボックスクリア { richTextBox3.Clear(); } private void ADCMonitor(uint adcValue) //LEDの状態をモニタ //デリゲート用の関数を定義 { int temp; double Volt; Volt = (adcValue * 3.3) / 4096; VR_textBox.Text = string.Format("{0:f2} [V]", Volt); //小数点以下2桁にして表示 //四捨五入 temp = (int)((((float)adcValue * 100) / 4096) + 0.5); //0.5を足して、小数点以下を切り捨てる VR_progressBar.Value = temp; } } }







<動作結果>           

動画  内容 備考
動画(システム全体)  システム全体の動きがわかります。  1080pのHD動画を見ることができます
動画(コマンド編) セントラルとペリフェラル間のコマンド送受信にフォーカスした動画です。
動画(PC 制御ウィンドウ編) PCの制御ウィンドウにフォーカスした動画です。

 
 ➀ PC画面から LED ON/OFF

モード LED ON  LED OFF  
画像   


 ➁ PIC側スイッチON/OFFの PC側でのモニタ

   モード    SW ON   SW OFF 
画像  


 ③ PIC側可変抵抗器電圧値の PC側でのモニタ 及び プログレスバーによる値のイメージ

 可変抵抗器電圧値  画像  備考 

約 0V
 
約 1.0V  
約 3.2V  



 ④ PC -PIC間 文字列の送受信
 

モード Japan を送信後
Tokyo を受信した時の画面
America を送信後
Washinton を受信した時の画面
U.K. を送信後
London を受信した時の画面
画像 
 モード France を送信後
Paris を受信した画面
How are you ? を送信後
Pardon ? を受信した画面
 
画像  


 

★ ペリフェラル側  コマンドに係る送受信のログ





★ セントラル側  コマンドに係る送受信ログ